package cn.pku.edu.cs.ldn.thread;

import java.util.LinkedList;
import java.util.List;

import android.util.Log;

/**
 * If you want to known how much this thread has run, just add a
 * ThreadObserverHandler object
 * 
 * @author ldn
 * 
 */
public abstract class ObservableThread extends InterruptibleThread {
	private static final String TAG = "ObservableThread";
	private static final boolean DEBUG = true;

	private List<ThreadObserverHandler> downloadThreadHandlers = null;

	public void addObserver(ThreadObserverHandler handler) {
		if (handler == null)
			return;
		synchronized (ObservableThread.this) {
			if (downloadThreadHandlers == null) {
				downloadThreadHandlers = new LinkedList<ThreadObserverHandler>();
			}
			if (downloadThreadHandlers.contains(downloadThreadHandlers) == false) {
				downloadThreadHandlers.add(handler);
			} else {
				if (DEBUG)
					Log.v(TAG, "addObserver: duplicate handler");
			}
		}
	}

	/**
	 * When all ThreadObserverHandler has been moved, this thread will be
	 * stopped
	 * 
	 * @param handler
	 * @return
	 */
	public boolean removeObserver(ThreadObserverHandler handler) {
		if (handler == null)
			return false;
		synchronized (ObservableThread.this) {
			if (downloadThreadHandlers == null) {
				return false;
			}
			boolean ret = downloadThreadHandlers.remove(downloadThreadHandlers);
			if (downloadThreadHandlers.isEmpty()) {
				requestStop();
			}
			return ret;
		}
	}

	public void notifyStart() {
		if (downloadThreadHandlers == null) {
			return;
		}
		for (ThreadObserverHandler handler : downloadThreadHandlers) {
			handler.notifyStart();
		}
	}

	public void notifyProgress(float progressed, float total) {
		if (downloadThreadHandlers == null) {
			return;
		}
		for (ThreadObserverHandler handler : downloadThreadHandlers) {
			handler.notifyProgress(progressed, total);
		}
	}

	public void notifyFinish(Object object) {
		if (downloadThreadHandlers == null) {
			return;
		}
		for (ThreadObserverHandler handler : downloadThreadHandlers) {
			handler.notifyFinish(object);
		}
	}

	@Override
	public abstract boolean requestStop();
}
